﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text;
using System.Threading.Tasks;
using Abp;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Configuration;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.Linq.Extensions;
using KDS.Mes.Mes.AlcCodes.Dtos;
using KDS.Mes.Authorization;
using KDS.Mes.Dto;
using KDS.Mes.Mes.Styles;
using KDS.Mes.Mes.Cartypes;
using Abp.UI;

namespace KDS.Mes.Mes.AlcCodes
{
    /// <summary>
    /// ALCCode信息服务实现
    /// </summary>
    [AbpAuthorize(AppPermissions.Pages_Bom_AlcCodes)]
    public class AlcCodeAppService : MesAppServiceBase, IAlcCodeAppService
    {
        private readonly IRepository<AlcCode, int> _alcCodeRepository;
        private readonly IAlcCodeListExcelExporter _alcCodeListExcelExporter;
        private readonly AlcCodeManage _alcCodeManage;
        private readonly IRepository<Style, int> _styleRepository;
        private readonly IRepository<Cartype, int> _cartypeRepository;
        /// <summary>
        /// 构造方法
        /// </summary>
        public AlcCodeAppService(
            IRepository<AlcCode, int> alcCodeRepository,
            AlcCodeManage alcCodeManage,
            IAlcCodeListExcelExporter alcCodeListExcelExporter,
            IRepository<Style, int> styleRepository,
            IRepository<Cartype, int> cartypeRepository
  )
        {
            _alcCodeRepository = alcCodeRepository;
            _alcCodeManage = alcCodeManage;
            _alcCodeListExcelExporter = alcCodeListExcelExporter;
            _styleRepository = styleRepository;
            _cartypeRepository = cartypeRepository;
        }

        #region ALCCode信息管理

        public async Task<ListResultDto<AlcCodeListDto>> GetalcCodes(GetAlcCodeInput input)
        {
            var alcCodes = await _alcCodeRepository.GetAll()
                .ToListAsync();

            return new ListResultDto<AlcCodeListDto>(alcCodes.MapTo<List<AlcCodeListDto>>());
        }

        public PagedResultDto<AlcCodeListDto> GetPagedAlcCodes(GetAlcCodeInput input)
        {
            //初步过滤
            //var query = _alcCodeRepository.GetAll();
            //初步过滤
            var query = from alc in _alcCodeRepository.GetAll().WhereIf(!input.AlcCode.IsNullOrEmpty(), u => u.ALCCode == input.AlcCode)
                        join st in _styleRepository.GetAll().WhereIf(!input.StyleId.IsNullOrEmpty(), u => u.Id.ToString() == input.StyleId) on alc.StyleId equals st.Id
                        join ct in _cartypeRepository.GetAll().WhereIf(!input.CartypeId.IsNullOrEmpty(), u => u.Id.ToString() == input.CartypeId) on st.CartypeId equals ct.Id
                        select new
                        {
                            alc,
                            CartypeName = ct.CartypeName
                        };
            //排序
            query = !string.IsNullOrEmpty(input.Sorting) ? query.OrderBy(x => x.alc.Id) : query.OrderByDescending(t => t.alc.CreationTime);
            //获取总数
            var tasksCount = query.Count();
            //默认的分页方式
            //ABP提供了扩展方法PageBy分页方式
            var taskList = query.PageBy(input).ToList();

            return new PagedResultDto<AlcCodeListDto>(
              tasksCount,
              taskList.Select(item =>
              {
                  var dto = item.alc.MapTo<AlcCodeListDto>();
                  dto.CartypeName = item.CartypeName;
                  return dto;
              }).ToList());

            //return new PagedResultDto<AlcCodeListDto>(tasksCount, taskList.MapTo<List<AlcCodeListDto>>());
        }

        /// <summary>
        /// 根据StyleId获取对应的AlcCodes
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public List<ComboboxItemDto> GetAllAlcCodeByStyleId(NullableIdDto<int> input)
        {
            List<ComboboxItemDto> output = new List<ComboboxItemDto>();
            var query = _alcCodeRepository.GetAll()
                .WhereIf(input.Id.HasValue, u => u.StyleId == input.Id).ToList();
            //query = query
            output = query
               .Select(c => new ComboboxItemDto(c.Id.ToString(), c.ALCCode))
               .ToList();
            return output;
        }

        /// <summary>
        /// 根据查询条件获取ALCCode信息分页列表
        /// </summary>
        public async Task<PagedResultDto<AlcCodeListDto>> GetPagedAlcCodesAsync(GetAlcCodeInput input)
        {

            var query = _alcCodeRepository.GetAll();
            //TODO:根据传入的参数添加过滤条件

            var alcCodeCount = await query.CountAsync();

            var alcCodes = await query
            .OrderBy(input.Sorting)
            .PageBy(input)
            .ToListAsync();

            var alcCodeListDtos = alcCodes.MapTo<List<AlcCodeListDto>>();
            return new PagedResultDto<AlcCodeListDto>(
            alcCodeCount,
            alcCodeListDtos
            );
        }

        /// <summary>
        /// 通过Id获取ALCCode信息信息进行编辑或修改 
        /// </summary>
        public async Task<GetAlcCodeForEditOutput> GetAlcCodeForEditAsync(NullableIdDto<int> input)
        {
            var output = new GetAlcCodeForEditOutput();

            AlcCodeEditDto alcCodeEditDto;

            if (input.Id.HasValue)
            {
                var entity = await _alcCodeRepository.GetAsync(input.Id.Value);
                alcCodeEditDto = entity.MapTo<AlcCodeEditDto>();

                output.AlcCode = alcCodeEditDto;

                var query = (from alc in _alcCodeRepository.GetAll()
                             join st in _styleRepository.GetAll() on alc.StyleId equals st.Id
                             where (st.Id == output.AlcCode.StyleId)
                             select new
                             {
                                 cartypeId = st.CartypeId,
                             }).ToList();
                output.Cartypes = _cartypeRepository.GetAllList()
                   .Select(c => new ComboboxItemDto(c.Id.ToString(), c.CartypeName) { IsSelected = query.FirstOrDefault().cartypeId == c.Id })
                   .ToList();

                output.Styles = _styleRepository.GetAllList()
                    .Where(c => c.CartypeId == query.FirstOrDefault().cartypeId)
                    .Select(c => new ComboboxItemDto(c.Id.ToString(), c.StyleName) { IsSelected = output.AlcCode.StyleId == c.Id })
                    .ToList();
            }
            else
            {
                alcCodeEditDto = new AlcCodeEditDto();

                output.AlcCode = alcCodeEditDto;
                output.Cartypes = _cartypeRepository.GetAllList()
               .Select(c => new ComboboxItemDto(c.Id.ToString(), c.CartypeName))
               .ToList();

                output.Styles = _styleRepository.GetAllList()
               .Where(c => c.CartypeId == int.Parse(output.Cartypes.FirstOrDefault().Value))
               .Select(c => new ComboboxItemDto(c.Id.ToString(), c.StyleName))
               .ToList();
            }

            //output.AlcCode = alcCodeEditDto;
            //output.Styles = _styleRepository.GetAllList()
            // .Select(c => new ComboboxItemDto(c.Id.ToString(), c.StyleName) { IsSelected = output.AlcCode.StyleId == c.Id })
            // .ToList();
            return output;
        }


        /// <summary>
        /// 通过指定id获取ALCCode信息ListDto信息
        /// </summary>
        public async Task<AlcCodeListDto> GetAlcCodeByIdAsync(EntityDto<int> input)
        {
            var entity = await _alcCodeRepository.GetAsync(input.Id);

            return entity.MapTo<AlcCodeListDto>();
        }







        /// <summary>
        /// 新增或更改ALCCode信息
        /// </summary>
        public async Task CreateOrUpdateAlcCodeAsync(CreateOrUpdateAlcCodeInput input)
        {
            if (input.AlcCodeEditDto.Id.HasValue)
            {
                await UpdateAlcCodeAsync(input.AlcCodeEditDto);
            }
            else
            {
                await CreateAlcCodeAsync(input.AlcCodeEditDto);
            }
        }

        /// <summary>
        /// 新增ALCCode信息
        /// </summary>
        [AbpAuthorize(AppPermissions.Pages_Bom_AlcCodes_Create)]
        public virtual async Task<AlcCodeEditDto> CreateAlcCodeAsync(AlcCodeEditDto input)
        {
            //TODO:新增前的逻辑判断，是否允许新增
            await CheckAlcCodeIfAlreadyExists(input.ALCCode, input.Id);
            var entity = input.MapTo<AlcCode>();

            entity = await _alcCodeRepository.InsertAsync(entity);
            return entity.MapTo<AlcCodeEditDto>();
        }

        /// <summary>
        /// 编辑ALCCode信息
        /// </summary>
        [AbpAuthorize(AppPermissions.Pages_Bom_AlcCodes_Edit)]
        public virtual async Task UpdateAlcCodeAsync(AlcCodeEditDto input)
        {
            //TODO:更新前的逻辑判断，是否允许更新
            await CheckAlcCodeIfAlreadyExists(input.ALCCode, input.Id);
            var entity = await _alcCodeRepository.GetAsync(input.Id.Value);
            input.MapTo(entity);

            await _alcCodeRepository.UpdateAsync(entity);
        }

        /// <summary>
        /// 删除ALCCode信息
        /// </summary>
        [AbpAuthorize(AppPermissions.Pages_Bom_AlcCodes_Delete)]
        public async Task DeleteAlcCodeAsync(EntityDto<int> input)
        {
            //TODO:删除前的逻辑判断，是否允许删除
            await _alcCodeRepository.DeleteAsync(input.Id);
        }

        /// <summary>
        /// 批量删除ALCCode信息
        /// </summary>
        [AbpAuthorize(AppPermissions.Pages_Bom_AlcCodes_Delete)]
        public async Task BatchDeleteAlcCodeAsync(List<int> input)
        {
            //TODO:批量删除前的逻辑判断，是否允许删除
            await _alcCodeRepository.DeleteAsync(s => input.Contains(s.Id));
        }

        private async Task CheckAlcCodeIfAlreadyExists(string alcCode, int? id = null)
        {
            var existingAlcCode = await _alcCodeRepository.GetAll()
                .FirstOrDefaultAsync(l => l.ALCCode == alcCode);
            if (existingAlcCode == null)
            {
                return;
            }

            if (id != null && existingAlcCode.Id == id)
            {
                return;
            }
            throw new UserFriendlyException(L("ThisAlcCodeAlreadyExists"));

        }

        #endregion


        #region ALCCode信息的Excel导出功能


        public async Task<FileDto> GetAlcCodeToExcel()
        {
            var entities = await _alcCodeRepository.GetAll().ToListAsync();

            var dtos = entities.MapTo<List<AlcCodeListDto>>();

            var fileDto = _alcCodeListExcelExporter.ExportAlcCodeToFile(dtos);



            return fileDto;
        }


        #endregion










    }
}
